package main;

import graph.UndirectedGraph;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Random;
import java.util.Set;

import utils.DegreeVector;
import utils.GraphUtils;
import utils.ListPair;


public class Driver {
	
	private static final int MAX_VERTICES = 20;
	private static String outputFile = "output/log.txt";

	public static void main(String[] args) {
//		InputReader reader = new InputReader();
//		String fileName = "input/test_input1";
//		List<DegreeVector> dvList = reader.readInputFromFile(fileName, ",");
//		DegreeSequenceBisection<Double> bisection = new DegreeSequenceBisection<Double>(dvList);
//		System.out.println(bisection.getSortedList().toString());
//		for(int i = 0; i < bisection.getSortedList().size(); i++) {
//			List<Integer> splitPoints = bisection.getPossibleSplittingPoints();
//			System.out.println("Possible split points after original sorting + " + i 
//					+ " moves of first element to back:" + splitPoints.toString());
//			bisection.moveFrontToBack();
//		}		
		
		GraphUtils utils = new GraphUtils();
		DegreeSequenceBisection<Double> bisection = null;
		List<Integer> splitPoints;
		Set<ListPair<DegreeVector>> bipartiteSplit;
		int numVertices, numEdges;
		int bipartiteCounter = 0;
		int graphCounter = 0;
		double minRatio = 1;
		
		FileWriter fstream = null;
		try {
			fstream = new FileWriter(outputFile, true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		BufferedWriter out = new BufferedWriter(fstream);
		try {
			out.append("\n" + (new GregorianCalendar()).getTime().toString().concat("\n")
					.concat("Max Vertices:") + MAX_VERTICES);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		for(int i = 0; i < 100; i++) {
			Random random = new Random();
			numVertices = Math.max(3, random.nextInt(MAX_VERTICES));
			int edgeMin = numVertices - 1;
			numEdges = Math.max(edgeMin, random.nextInt(numVertices*(numVertices-1)/2));
			try {
				UndirectedGraph g = new UndirectedGraph<String, Double>(numVertices, numEdges, true, true);
				List<DegreeVector> vectors = utils.makeDegreeVectors(g, g.getPartition());
				System.out.println(g.toString());
				System.out.println(g.getPartition());
				bisection = new DegreeSequenceBisection<Double>(vectors);
				bipartiteSplit = bisection.findBipartiteSplitting(false);
				if(bipartiteSplit.size() > 0) {
					bipartiteCounter++;
					String bipartiteString = "\n" + bipartiteSplit.size() + " Bipartite split(s) for graph "
							+ i + " with # vertices = " + g.getVertexCount() + ", # edges=" + g.getEdgeCount() + ".\n";
					System.out.println(bipartiteString);
					try {
						out.append(bipartiteString);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					boolean success = false;
					for(ListPair<DegreeVector> pair : bipartiteSplit) {
						if(!success && utils.isGraphic(pair.getLeftList(), 0) 
								&& utils.isGraphic(pair.getRightList(), 0)) {
							success = true;
							graphCounter++;
						}
					}
					if(success) {
						System.out.println("GRAPH FOUND!");
						try {
							out.append("\nGRAPH FOUND!");
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					if((double)bipartiteSplit.size()/(double)g.getVertexCount() < minRatio)
						minRatio = (double)bipartiteSplit.size()/(double)g.getVertexCount();
				}
				g = null;
				vectors = null;
			} catch (Exception e) {
				--i;
//				e.printStackTrace();
				System.out.println(e.getMessage());
			}
		}
		String bipartiteResultString = "Num found: "+bipartiteCounter +", min ratio: " + minRatio;
		System.out.println(bipartiteResultString);
		String graphResultString = "Number graphs found: " + graphCounter;
		System.out.println(graphResultString);
		try {
			out.append("\n"+bipartiteResultString.concat("\n").concat(graphResultString).concat("\n")
					.concat("Required Bipartite ratio: ") + bisection.REQUIRED_BIPARTITE_RATIO
					+ "\n".concat("Number subset-sum tries: ") + bisection.NUM_SUBSET_SUM_TRIES
					+ "\n".concat("Approximation parameter: ") + bisection.APPROXIMATION_PARAMETER);
			out.append("\n");
			out.close();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
